package ext.tianma.masschange.util;

import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import wt.change2.ChangeHelper2;
import wt.change2.ChangeItemIfc;
import wt.change2.Changeable2;
import wt.change2.WTChangeActivity2;
import wt.enterprise.RevisionControlled;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.WTObject;
import wt.lifecycle.LifeCycleHelper;
import wt.lifecycle.LifeCycleManaged;
import wt.lifecycle.State;
import wt.method.RemoteAccess;
import wt.part.WTPart;
import wt.part.WTPartHelper;
import wt.part.WTPartMaster;
import wt.part.WTPartSubstituteLink;
import wt.part.WTPartUsageLink;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.vc.Iterated;
import wt.vc.VersionControlHelper;
import wt.vc.config.ConfigHelper;
import wt.vc.config.ConfigSpec;
import wt.vc.config.LatestConfigSpec;
import wt.vc.struct.StructHelper;

import com.ptc.core.components.descriptor.ModelContext;
import com.ptc.netmarkets.model.NmOid;
import com.ptc.netmarkets.util.beans.NmCommandBean;

public class MassChangeUtil implements RemoteAccess,Serializable{
	
	private static String RESOURCE = "ext.tianma.masschange.resource.MassChangeResource";
	private static String CLASSNAME="";
	private static boolean VERBOSE = false;
	private static WTProperties wtProperties;
	private static Locale locale = null;

	static {

		try {
			CLASSNAME= MassChangeUtil.class.getName();
			wtProperties = WTProperties.getLocalProperties();
			locale = SessionHelper.manager.getLocale();
			VERBOSE = wtProperties.getProperty("ext.tianma.masschange.util.verbose", false);
		}
		catch (IOException ioe) {
			ioe.printStackTrace();
		}catch (Throwable throwable) {
			throw new ExceptionInInitializerError(throwable);
		}
	}
	
	public MassChangeUtil() {

	}
	  /**
	 *输出调试信息
	 */
	private static void outDebugInfo(String info) {
		if(VERBOSE)
			System.out.println(CLASSNAME+"......"+info);
	}
	
	/**
     * 根据对象，判断该对象是否是某个未关闭的ca的受影响数据或最后所得项
	 **/
    public static boolean hasCA(Changeable2 changeable, ModelContext mc)
    	throws WTException
    {
    	//如果对象为空，返回false
    	if(changeable == null)
    	{
    		return false;
    	}
    	else
    	{
    		//获取当前CA
    		NmOid nmoid = mc.getNmCommandBean().getPrimaryOid();
        	WTObject wtobject = (WTObject) nmoid.getWtRef().getObject();
        	WTChangeActivity2 currentCA = null;
        	if(wtobject instanceof WTChangeActivity2) {
        		currentCA = (WTChangeActivity2)wtobject;
        	}
        	
			/*QueryResult qr = ChangeHelper2.service.getAffectingChangeActivities(changeable); //受影响数据
			while(qr.hasMoreElements())
			{
				WTChangeActivity2 ca = (WTChangeActivity2)qr.nextElement(); 
				//是否为当前CA
				if(ca.equals(currentCA))
					return false;
				String curState =((WTChangeActivity2)ca).getLifeCycleState().toString();
				if(! (curState.equals("RESOLVED")) || (curState.equals("CANCELLED")))
					return true;
			}*/
			
        	QueryResult qr = ChangeHelper2.service.getImplementedChangeActivities(changeable); //最后所得项
			while(qr.hasMoreElements())
			{
				WTChangeActivity2 ca = (WTChangeActivity2)qr.nextElement(); 
				//是否为当前CA
				if(ca.equals(currentCA))
					return false;
				String curState =((WTChangeActivity2)ca).getLifeCycleState().toString();
				if(! (curState.equals("RESOLVED")) || (curState.equals("CANCELLED")))
					return true;
			}
		}
		return false;
    }
    
    public static boolean inCurrentCA(Changeable2 changeable, WTChangeActivity2 currentCA) throws WTException {
    	QueryResult qr = ChangeHelper2.service.getImplementedChangeActivities(changeable); //最后所得项
		while(qr.hasMoreElements())
		{
			WTChangeActivity2 ca = (WTChangeActivity2)qr.nextElement(); 
			//是否为当前CA
			if(ca.equals(currentCA))
				return true;
		}
		return false;
    }
    
    
    /**
	 * 根据零部件，获取零部件的所有直接父件的列表，列表中不包括零部件本身
	 * @param part 想要获取父件的零部件
	 * @return 返回该零部件的所有父件列表。如果部件为空，返回空；如果没有父件，返回空
	 * @throws WTException
	 * <br><br>
	 * <b>Revision History</b>
	 * <br><b>Rev:</b> 1.0 - 2006/03/17, Gaoxu
	 * <br><b>Comment:</b> Initial release.
	 */
	public static Vector getParentPartListByPart(WTPart part) throws WTException {
		Vector parents = new Vector();
		try {
			WTPartMaster part_master = (WTPartMaster)part.getMaster();
			WTPartUsageLink usagelink[] = null;
			QueryResult queryresult = StructHelper.service.navigateUsedBy(part_master, true);
			while(queryresult.hasMoreElements()) {
				WTPart parent = (WTPart)queryresult.nextElement();
				if(isPersistableInobjVector(parents, parent)) {
					if(parent!=null)
						parents.addElement(parent);
				}
			}
		}
		catch (WTException wte) {
			wte.printStackTrace();
		}	
		return parents;
	}
	
	/**
	 * 检查某一个可持续对象是否在列表中
	 * @param objVector 检查的列表
	 * @param destination 想要检查的对象
	 * @return 如果对象在列表中，返回true，否则，返回false  
	 * @throws WTException
	 *
	 * <br><br>
	 * <b>Revision History</b>
	 * <br><b>Rev:</b> 1.0 - 2006/03/30, Easy Wang
	 * <br><b>Comment:</b> Initial release.
	 */
	public static boolean isPersistableInobjVector(Vector objVector, Persistable destination) throws WTException {
		if((objVector==null) || (objVector.size()<=0))
			return false;
		if(objVector.contains(destination)) {
			return true;
		}
		boolean flag= false;
		for(int i=0; i<objVector.size(); i++) {
			flag= PersistenceHelper.isEquivalent((Persistable)objVector.elementAt(i), destination);
			if(flag)
				return flag;
		}
		return flag;
	}
	
	/**
	 * 获得两个部件之间的关联列表
	 * @param parentPart 所需判定的关系层级中的父件
	 * @param childPart 所需判定的关系层级中的子件
	 * @return 两个零部件之间的关联列表
	 * @throws WTException
	 */
	public static Vector getPartUsageLink(WTPart parentPart, WTPart childPart)throws WTException {
		Vector usageLinkV = new Vector();
		if(parentPart==null||childPart==null)
			return null;
		//得到和父件关联的所有第一层子件.如果没关联子件返回false
		QueryResult subParts = WTPartHelper.service.getUsesWTPartMasters(parentPart);
		if(subParts !=null && subParts.size()<=0)
			return null;
		
		//逐个搜索给定的零部件是不是父件的子件
		while(subParts.hasMoreElements())	    
		{   
			WTPartUsageLink usageLink =(WTPartUsageLink)subParts.nextElement();
			WTPartMaster partMaster =(WTPartMaster)usageLink.getUses();
			WTPart child=getLatestPartByPartMaster(partMaster);
			if(child.getNumber().equalsIgnoreCase(childPart.getNumber()))
				usageLinkV.addElement(usageLink);
		} 
		
		return usageLinkV;
	}
	
	/**
	 * 根据零部件的master，获取零部件的最新小版本
	 * @param partMaster 想要获取最新小版本的零部件的master
	 * @return 返回该master对应的最新小版本的零部件，如果master为空，返回空
	 * @throws WTException
	 * <br><br>
	 * <b>Revision History</b>
	 * <br><b>Rev:</b> 1.0 - 2006/03/15, Gaoxu
	 * <br><b>Rev:</b> 1.1 - 2006/09/11, Peter Duan
	 * <br><b>Comment:</b> Initial release.
	 */
	public static WTPart getLatestPartByPartMaster(WTPartMaster partMaster) throws WTException {
		Iterated iter=null; 
		boolean flag=false;
		LatestConfigSpec latestconfigspec = new LatestConfigSpec();
		//根据零部件的master和latestconfigspec得到该master的所有小版本
		QueryResult queryresult = ConfigHelper.service.filteredIterationsOf(partMaster, latestconfigspec);
		if(queryresult !=null && queryresult.size()<=0)
		{
			ConfigSpec configspec = ConfigHelper.service.getDefaultConfigSpecFor(WTPartMaster.class);
			queryresult = ConfigHelper.service.filteredIterationsOf(partMaster, configspec);
		}
		
		while( queryresult.hasMoreElements() && (!flag) )
		{ 
			iter = (Iterated)(queryresult.nextElement());
			flag = iter.isLatestIteration();
		}

		return (WTPart)iter;
	}
	
	/**
	 * 判断是否为当前视图最新版本
	 * @param part
	 * @return boolean
	 * @throws WTException
	 */
	public static boolean isLatestVersion(WTPart part) throws WTException {
		ConfigSpec configspec = ConfigHelper.service.getConfigSpecFor(part);
		QueryResult queryresult = ConfigHelper.service.filteredIterationsOf(part.getMaster(), configspec);
		Iterated iterated = (Iterated)queryresult.nextElement();
		if(PersistenceHelper.isEquivalent(iterated, part))
			return true;
		else
			return false;
	}
	
	/**
	 * 判断一个生命周期状态是否为某一字符串
	 */
	public static boolean equalState(LifeCycleManaged lcm, String state) {
		boolean flag = false;
		String currentState = lcm.getLifeCycleState().toString();
		if(currentState.equalsIgnoreCase(state)) {
			flag = true;
		}	
		return flag;
	}
	
	/**
	 * 修订part
	 * @param part
	 * @return
	 * @throws WTException
	 */
	public static WTPart revisePart(WTPart part) throws WTException {
		WTPart newRevisonPart = null;
		RevisionControlled revision = (RevisionControlled)part;
		RevisionControlled newRevision=null;
		try {
			newRevision = (RevisionControlled)VersionControlHelper.service.newVersion(revision);
		} catch (WTPropertyVetoException e) {
			e.printStackTrace();
		} 
		newRevision = (RevisionControlled)PersistenceHelper.manager.save(newRevision);
		newRevisonPart = (WTPart)newRevision;
		return newRevisonPart;
	}
	
	/**
	 * 往变更对象中添加数据
	 * @param ca
	 * @param changeObjs
	 * @param className
	 * @throws Exception
	 */
	public static void addChangeObjs(WTChangeActivity2 ca,Vector changeObjs,String className) throws Exception
	{
		ChangeItemIfc cii=(ChangeItemIfc)ca;
		Class class1 = null;
		Vector addToChangeObjs = new Vector();
		//add changeAfter
		if(className.equals("wt.change2.ChangeRecord2"))
		{
			class1 = Class.forName("wt.change2.ChangeRecord2");
			Vector after_vector = new Vector();
			after_vector =(ChangeHelper2.service.getChangeablesAfter(ca)).getObjectVectorIfc().getVector();
			for(int i=0;i<changeObjs.size();i++)
			{
				WTPart part = (WTPart)changeObjs.elementAt(i);
				if(!after_vector.contains(part)&&!addToChangeObjs.contains(part))
				{
					addToChangeObjs.add(part);
					outDebugInfo("&&&&&&&&&&&&&& ADD "+part.getDisplayIdentity().toString()+" to addToChangeObjs");
				}
			}
		}
		//add changeBefore
		if(className.equals("wt.change2.AffectedActivityData"))
		{
			class1 = Class.forName("wt.change2.AffectedActivityData");
			Vector before_vector = new Vector();
			before_vector =(ChangeHelper2.service.getChangeablesBefore(ca)).getObjectVectorIfc().getVector();
			for(int i=0;i<changeObjs.size();i++)
			{
				WTPart part = (WTPart)changeObjs.elementAt(i);
				if(!before_vector.contains(part)&&!addToChangeObjs.contains(part))
				{
					addToChangeObjs.add(part);
					outDebugInfo("&&&&&&&&&&&&&& ADD "+part.getDisplayIdentity().toString()+" to addToChangeObjs");
				}
			}
		}
		//process add
		ChangeHelper2.service.storeAssociations(class1, cii, addToChangeObjs);
	}
	
	
	
	/** 
	* 使用java正则表达式去掉多余的.与0 
	* @param s 
	* @return  
	*/  
	public static String subZeroAndDot(String s) {  
		if(s.indexOf(".") > 0) {  
			s = s.replaceAll("0+?$", "");//去掉多余的0  
	        s = s.replaceAll("[.]$", "");//如最后一位是.则去掉  
	      }  
	    return s;  
	}
	
	/**
	 * 判断字符串是否为数字
	 * @param str
	 * @return
	 */
	public static boolean isNum(String str) {		
		return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");	
	}
	
	/**
	 * 对JS方法中通过escape加密的字符串进行解密
	 * @param src
	 * @return
	 */
	public static String unescape(String src) {  
		StringBuffer tmp = new StringBuffer();  
        tmp.ensureCapacity(src.length());  
        int lastPos = 0, pos = 0;  
        char ch;  
        while (lastPos < src.length()) {  
            pos = src.indexOf("%", lastPos);  
            if (pos == lastPos) {  
                if (src.charAt(pos + 1) == 'u') {  
                    ch = (char) Integer.parseInt(src  
                            .substring(pos + 2, pos + 6), 16);  
                    tmp.append(ch);  
                    lastPos = pos + 6;  
                } else {  
                    ch = (char) Integer.parseInt(src  
                            .substring(pos + 1, pos + 3), 16);  
                    tmp.append(ch);  
                    lastPos = pos + 3;  
                }  
            } else {  
                if (pos == -1) {  
                    tmp.append(src.substring(lastPos));  
                    lastPos = src.length();  
                } else {  
                    tmp.append(src.substring(lastPos, pos));  
                    lastPos = pos;  
                }  
            }  
        }  
        return tmp.toString();  
    }
	
	/**
	 * 设置某个对象的生命周期状态
	 * @param obj
	 * @param toState
	 * @throws WTException
	 */
	public static void setState(WTObject obj, String toState) throws WTException {
		boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
	    try {
	    	if(obj instanceof LifeCycleManaged) {
	    		LifeCycleManaged lcm = (LifeCycleManaged)obj;
	            String currentlcmState = lcm.getLifeCycleState().toString();
	            if(!currentlcmState.equals(toState)){
	                try {
	                    lcm = LifeCycleHelper.service.setLifeCycleState(lcm, State.toState(toState));
	                }
					catch(Exception e)
					{
	                    e.printStackTrace();
	                }
				}
	        }
	    } 
		finally 
		{
			SessionServerHelper.manager.setAccessEnforced(flag);
	    }
	}
	
	/**
	 * 判断两个零件之间是否有特定替代关系
	 * @param parent
	 * @param child
	 * @return
	 * @throws WTException
	 */
	public static boolean hasPartSubstituteLink(WTPartUsageLink usageLink,WTPartMaster master) throws WTException {
		QueryResult qr = PersistenceHelper.manager.navigate(usageLink,WTPartSubstituteLink.SUBSTITUTES_ROLE,WTPartSubstituteLink.class);
		while(qr.hasMoreElements()){
			WTPartMaster substituteMaster = (WTPartMaster)qr.nextElement();
			if(substituteMaster.equals(master)) {
				return true; 
			}
		}
		return false;
	}
	
	/**
	 * 获取替代关系
	 * @param usageLink
	 * @param master
	 * @return
	 * @throws WTException
	 */
	public static WTPartSubstituteLink getPartSubstituteLink (WTPartUsageLink usageLink,WTPartMaster master) throws WTException {
		String[] sb = master.toString().split(":");
		String[] sa = usageLink.toString().split(":");
		long idB = Long.parseLong(sb[1]);
		long idA = Long.parseLong(sa[1]);
		QuerySpec queryspec = new QuerySpec(wt.part.WTPartSubstituteLink.class);
		queryspec.appendWhere(new SearchCondition(wt.part.WTPartSubstituteLink.class, "roleBObjectRef.key.id", "=", idB));
		queryspec.appendAnd();
		queryspec.appendWhere(new SearchCondition(wt.part.WTPartSubstituteLink.class, "roleAObjectRef.key.id", "=", idA));
		QueryResult queryresult = PersistenceHelper.manager.find(queryspec);
		WTPartSubstituteLink substituteLink = (WTPartSubstituteLink)queryresult.nextElement();
		return substituteLink;
	}
	
	/**
	 * 获取usageLink上所有替代link
	 * @param usageLink
	 * @return
	 * @throws WTException
	 */
	public static QueryResult getPartSubstituteLinks(WTPartUsageLink usageLink) throws WTException {
		String[] sa = usageLink.toString().split(":");
		long idA = Long.parseLong(sa[1]);
		QuerySpec queryspec = new QuerySpec(wt.part.WTPartSubstituteLink.class);
		queryspec.appendWhere(new SearchCondition(wt.part.WTPartSubstituteLink.class, "roleAObjectRef.key.id", "=", idA));
		QueryResult queryresult = PersistenceHelper.manager.find(queryspec);
		return queryresult;
	}
	
	
	
	/**
	 * 新建替代关系
	 * @param usageLink
	 * @param master
	 * @throws WTException
	 */
	public static void createSubstitute(WTPartUsageLink usageLink,WTPartMaster master)	 throws WTException {
		WTPartSubstituteLink substituteLink=WTPartSubstituteLink.newWTPartSubstituteLink(usageLink,master);
		substituteLink= (WTPartSubstituteLink)PersistenceHelper.manager.store(substituteLink);
	}
	
	/**
	 * 删除替代关系
	 * @param usageLink
	 * @param master
	 * @throws WTException
	 */
	public static void deleteSubstitute(WTPartUsageLink usageLink, WTPartMaster master) throws WTException {
		WTPartSubstituteLink substituteLink = getPartSubstituteLink(usageLink, master);
		PersistenceHelper.manager.delete(substituteLink);
	}
	
	
	
	/**
	 * 输出nmcommandbean
	 * @param nmcommandbean
	 */
	public static void printRequestParameterMap(NmCommandBean nmcommandbean ){
		
		System.out.println("===== Start printRequestParameterMap =====") ;
		
		Map<String,String[]> requestMap = nmcommandbean.getRequest().getParameterMap() ;
		
		if(requestMap == null){
			System.out.println(">>>>> printRequestParameterMap parameter Map is NULL") ;
			return ;
		}
		
		Set<String> keySet = requestMap.keySet() ;
		Iterator<String> keySetIte = keySet.iterator();
		while(keySetIte.hasNext()){
			String key = keySetIte.next() ;
			String[] values = requestMap.get(key) ;
			
			String value = "" ;
			if(values == null){
				value = "[ NULL ]" ;
			}else if(values.length == 0){
				value = "[ 0 ]" ;
			}else{
				value = "[ " ;
				for(int i=0 ; i < values.length ; i ++){
					value = value + values[i] + " , " ;
				}
				
				if(value.endsWith(" , ")){
					value = value.substring(0, value.indexOf(" , ")) ;
				}
				
				value = value + " ]" ;
			}
			
			System.out.println(key + " ======> " + value) ;
		}
		
		System.out.println("====== End printRequestParameterMap ======") ;
	}
}
